// core/storage_core.c

#include <string.h>
#include "esp_log.h"
#include "esp_littlefs.h"
#include "esp_vfs_littlefs.h"  // 使用LittleFS VFS接口
#include "esp_check.h"
#include "storage_types.h"

static const char *TAG = "storage_core";

esp_err_t storage_init(storage_context_t* ctx, const storage_config_t* config)
{
    // 参数检查
    ESP_RETURN_ON_FALSE(ctx && config, ESP_ERR_INVALID_ARG, TAG, "Invalid args");
    ESP_RETURN_ON_FALSE(config->base_path[0] == '/', ESP_ERR_INVALID_ARG, TAG, "Base path must start with /");

    esp_err_t ret = ESP_OK;

    // 配置LittleFS
    esp_vfs_littlefs_conf_t lfs_conf = {
        .base_path = config->base_path,
        .partition_label = config->partition_label,
        .format_if_mount_failed = config->format_if_mount_failed,
        // 使用LittleFS默认配置
        .max_files = CONFIG_LITTLEFS_MAX_OPEN_FILES
    };

    // 尝试挂载LittleFS
    ret = esp_vfs_littlefs_register(&lfs_conf);
    if (ret == ESP_FAIL && config->format_if_mount_failed) {
        // 如果挂载失败并允许格式化,则先格式化
        ESP_LOGW(TAG, "Failed to mount filesystem, formatting...");
        ret = esp_littlefs_format(config->partition_label);
        if (ret != ESP_OK) {
            ESP_LOGE(TAG, "Failed to format filesystem");
            return ret;
        }
        // 格式化后重新挂载
        ret = esp_vfs_littlefs_register(&lfs_conf);
    }

    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize filesystem");
        return ret;
    }

    // 创建互斥锁
    ctx->mutex = xSemaphoreCreateMutex();
    if (ctx->mutex == NULL) {
        esp_vfs_littlefs_unregister(config->partition_label);
        return ESP_ERR_NO_MEM;
    }

    // 获取存储信息
    size_t total_bytes = 0, used_bytes = 0;
    ret = esp_littlefs_info(config->partition_label, &total_bytes, &used_bytes);
    if (ret == ESP_OK) {
        ctx->info.total_bytes = total_bytes;
        ctx->info.used_bytes = used_bytes;
        ctx->info.free_bytes = total_bytes - used_bytes;
    } else {
        ESP_LOGW(TAG, "Failed to get filesystem info");
    }

    // 保存配置
    memcpy(&ctx->config, config, sizeof(storage_config_t));
    ctx->state = STORAGE_STATE_MOUNTED;

    ESP_LOGI(TAG, "Filesystem initialized, total: %u bytes, used: %u bytes",
             (unsigned)total_bytes, (unsigned)used_bytes);

    return ESP_OK;
}

// core/storage_core.c 继续

esp_err_t storage_deinit(storage_context_t* ctx)
{
    // 参数检查
    ESP_RETURN_ON_FALSE(ctx && ctx->state == STORAGE_STATE_MOUNTED,
                       ESP_ERR_INVALID_STATE, TAG, "Invalid state");

    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    // 关闭所有打开的文件
    esp_vfs_littlefs_close_files(ctx->config.partition_label);

    // 卸载LittleFS
    esp_err_t ret = esp_vfs_littlefs_unregister(ctx->config.partition_label);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to unmount filesystem: %s", esp_err_to_name(ret));
        xSemaphoreGive(ctx->mutex);
        return ret;
    }

    // 清理资源
    vSemaphoreDelete(ctx->mutex);
    ctx->mutex = NULL;
    ctx->state = STORAGE_STATE_UNMOUNTED;
    memset(&ctx->info, 0, sizeof(storage_info_t));

    ESP_LOGI(TAG, "Filesystem unmounted");
    return ESP_OK;
}



esp_err_t storage_format(storage_context_t* ctx)
{
    // 参数检查
    ESP_RETURN_ON_FALSE(ctx && ctx->state == STORAGE_STATE_MOUNTED,
                       ESP_ERR_INVALID_STATE, TAG, "Invalid state");

    esp_err_t ret;
    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    // 关闭所有打开的文件
    esp_vfs_littlefs_close_files(ctx->config.partition_label);

    // 卸载文件系统
    ret = esp_vfs_littlefs_unregister(ctx->config.partition_label);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to unmount filesystem: %s", esp_err_to_name(ret));
        xSemaphoreGive(ctx->mutex);
        return ret;
    }

    // 格式化文件系统
    ret = esp_littlefs_format(ctx->config.partition_label);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to format filesystem: %s", esp_err_to_name(ret));
        xSemaphoreGive(ctx->mutex);
        return ret;
    }

    // 重新挂载文件系统
    esp_vfs_littlefs_conf_t conf = {
        .base_path = ctx->config.base_path,
        .partition_label = ctx->config.partition_label,
        .format_if_mount_failed = true,
        .max_files = CONFIG_LITTLEFS_MAX_OPEN_FILES
    };

    ret = esp_vfs_littlefs_register(&conf);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to mount filesystem after format: %s", esp_err_to_name(ret));
        xSemaphoreGive(ctx->mutex);
        return ret;
    }

    // 更新存储信息
    size_t total_bytes = 0, used_bytes = 0;
    ret = esp_littlefs_info(ctx->config.partition_label, &total_bytes, &used_bytes);
    if (ret == ESP_OK) {
        ctx->info.total_bytes = total_bytes;
        ctx->info.used_bytes = 0;
        ctx->info.free_bytes = total_bytes;
    }

    xSemaphoreGive(ctx->mutex);
    ESP_LOGI(TAG, "Filesystem formatted successfully");

    return ESP_OK;
}


// core/storage_ops.c

#include <string.h>
#include "esp_log.h"
#include "esp_littlefs.h"
#include "esp_vfs_littlefs.h"
#include "esp_check.h"
#include "storage_types.h"

static const char *TAG = "storage_ops";

esp_err_t storage_read(storage_context_t* ctx, const char* path,
                      void* data, size_t size, size_t* read_size)
{
    // 参数检查
    ESP_RETURN_ON_FALSE(ctx && path && data && read_size && size > 0,
                       ESP_ERR_INVALID_ARG, TAG, "Invalid args");
    ESP_RETURN_ON_FALSE(ctx->state == STORAGE_STATE_MOUNTED,
                       ESP_ERR_INVALID_STATE, TAG, "Not mounted");

    esp_err_t ret = ESP_OK;
    char full_path[CONFIG_LITTLEFS_MAX_NAME_LENGTH];

    // 构建完整路径
    if (snprintf(full_path, sizeof(full_path), "%s%s",
                 ctx->config.base_path, path) >= sizeof(full_path)) {
        return ESP_ERR_BUFFER_OVERFLOW;
    }

    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    // 获取文件信息
    esp_littlefs_file_stat_t file_stat;
    ret = esp_littlefs_stat(ctx->config.partition_label, full_path, &file_stat);
    if (ret != ESP_OK) {
        ESP_LOGW(TAG, "File %s not found", full_path);
        xSemaphoreGive(ctx->mutex);
        return ESP_ERR_NOT_FOUND;
    }

    // 使用LittleFS专用API打开文件
    lfs_file_t* lfs_file;
    ret = esp_littlefs_fopen(ctx->config.partition_label, full_path, "rb", &lfs_file);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to open file %s", full_path);
        xSemaphoreGive(ctx->mutex);
        return ret;
    }

    // 使用LittleFS读取
    *read_size = esp_littlefs_fread(lfs_file, data, size);
    if (*read_size == 0 && ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read file %s", full_path);
        ret = ESP_FAIL;
    } else {
        ctx->stats.operations.reads++;
        ctx->stats.operations.read_bytes += *read_size;
    }

    // 关闭文件
    esp_littlefs_fclose(lfs_file);
    xSemaphoreGive(ctx->mutex);

    return ret;
}

esp_err_t storage_write(storage_context_t* ctx, const char* path,
                       const void* data, size_t size)
{
    // 参数检查
    ESP_RETURN_ON_FALSE(ctx && path && (data || size == 0),
                       ESP_ERR_INVALID_ARG, TAG, "Invalid args");
    ESP_RETURN_ON_FALSE(ctx->state == STORAGE_STATE_MOUNTED,
                       ESP_ERR_INVALID_STATE, TAG, "Not mounted");

    // 检查可用空间
    esp_littlefs_free_bytes_t free_bytes;
    esp_err_t ret = esp_littlefs_free(ctx->config.partition_label, &free_bytes);
    if (ret != ESP_OK || free_bytes.bytes_free < size) {
        return ESP_ERR_NO_MEM;
    }

    char full_path[CONFIG_LITTLEFS_MAX_NAME_LENGTH];
    if (snprintf(full_path, sizeof(full_path), "%s%s",
                 ctx->config.base_path, path) >= sizeof(full_path)) {
        return ESP_ERR_BUFFER_OVERFLOW;
    }

    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    // 使用LittleFS专用API创建和打开文件
    lfs_file_t* lfs_file;
    ret = esp_littlefs_fopen(ctx->config.partition_label, full_path, "wb", &lfs_file);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to create file %s", full_path);
        xSemaphoreGive(ctx->mutex);
        return ret;
    }

    // 使用LittleFS写入
    size_t written = esp_littlefs_fwrite(lfs_file, data, size);
    if (written != size) {
        ESP_LOGE(TAG, "Failed to write file %s", full_path);
        ret = ESP_FAIL;
    } else {
        // 刷新到存储
        ret = esp_littlefs_fsync(lfs_file);
        if (ret == ESP_OK) {
            ctx->stats.operations.writes++;
            ctx->stats.operations.write_bytes += written;

            // 更新存储信息
            size_t total_bytes = 0, used_bytes = 0;
            if (esp_littlefs_info(ctx->config.partition_label, 
                                &total_bytes, &used_bytes) == ESP_OK) {
                ctx->info.used_bytes = used_bytes;
                ctx->info.free_bytes = total_bytes - used_bytes;
            }
        }
    }

    esp_littlefs_fclose(lfs_file);
    xSemaphoreGive(ctx->mutex);

    return ret;
}


// core/storage_ops.c 继续

esp_err_t storage_remove(storage_context_t* ctx, const char* path)
{
    ESP_RETURN_ON_FALSE(ctx && path, ESP_ERR_INVALID_ARG, TAG, "Invalid args");
    ESP_RETURN_ON_FALSE(ctx->state == STORAGE_STATE_MOUNTED, 
                       ESP_ERR_INVALID_STATE, TAG, "Not mounted");

    char full_path[CONFIG_LITTLEFS_MAX_NAME_LENGTH];
    if (snprintf(full_path, sizeof(full_path), "%s%s",
                 ctx->config.base_path, path) >= sizeof(full_path)) {
        return ESP_ERR_BUFFER_OVERFLOW;
    }

    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    // 获取文件信息用于更新统计
    esp_littlefs_file_stat_t file_stat;
    esp_err_t ret = esp_littlefs_stat(ctx->config.partition_label, full_path, &file_stat);
    if (ret != ESP_OK) {
        xSemaphoreGive(ctx->mutex);
        return ret;
    }

    // 使用LittleFS删除文件
    ret = esp_littlefs_unlink(ctx->config.partition_label, full_path);
    if (ret == ESP_OK) {
        ctx->stats.operations.deletes++;
        
        // 更新存储信息
        size_t total_bytes = 0, used_bytes = 0;
        if (esp_littlefs_info(ctx->config.partition_label, &total_bytes, &used_bytes) == ESP_OK) {
            ctx->info.used_bytes = used_bytes;
            ctx->info.free_bytes = total_bytes - used_bytes;
        }
    }

    xSemaphoreGive(ctx->mutex);
    return ret;
}

esp_err_t storage_rename(storage_context_t* ctx, const char* old_path, const char* new_path)
{
    ESP_RETURN_ON_FALSE(ctx && old_path && new_path, 
                       ESP_ERR_INVALID_ARG, TAG, "Invalid args");
    ESP_RETURN_ON_FALSE(ctx->state == STORAGE_STATE_MOUNTED, 
                       ESP_ERR_INVALID_STATE, TAG, "Not mounted");

    char old_full_path[CONFIG_LITTLEFS_MAX_NAME_LENGTH];
    char new_full_path[CONFIG_LITTLEFS_MAX_NAME_LENGTH];

    if (snprintf(old_full_path, sizeof(old_full_path), "%s%s",
                 ctx->config.base_path, old_path) >= sizeof(old_full_path) ||
        snprintf(new_full_path, sizeof(new_full_path), "%s%s",
                 ctx->config.base_path, new_path) >= sizeof(new_full_path)) {
        return ESP_ERR_BUFFER_OVERFLOW;
    }

    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    // 使用LittleFS重命名文件
    esp_err_t ret = esp_littlefs_rename(ctx->config.partition_label, 
                                      old_full_path, new_full_path);

    xSemaphoreGive(ctx->mutex);
    return ret;
}

esp_err_t storage_stat(storage_context_t* ctx, const char* path, storage_file_info_t* info)
{
    ESP_RETURN_ON_FALSE(ctx && path && info, 
                       ESP_ERR_INVALID_ARG, TAG, "Invalid args");
    ESP_RETURN_ON_FALSE(ctx->state == STORAGE_STATE_MOUNTED, 
                       ESP_ERR_INVALID_STATE, TAG, "Not mounted");

    char full_path[CONFIG_LITTLEFS_MAX_NAME_LENGTH];
    if (snprintf(full_path, sizeof(full_path), "%s%s",
                 ctx->config.base_path, path) >= sizeof(full_path)) {
        return ESP_ERR_BUFFER_OVERFLOW;
    }

    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    esp_littlefs_file_stat_t file_stat;
    esp_err_t ret = esp_littlefs_stat(ctx->config.partition_label, full_path, &file_stat);
    
    if (ret == ESP_OK) {
        // 填充文件信息
        info->size = file_stat.size;
        info->type = file_stat.type == ESP_LITTLEFS_TYPE_DIR ? 
                    STORAGE_TYPE_DIRECTORY : STORAGE_TYPE_REGULAR;
        info->create_time = file_stat.ctime;
        info->modify_time = file_stat.mtime;
        info->permissions = STORAGE_PERM_READ | STORAGE_PERM_WRITE;
        strlcpy(info->name, path, sizeof(info->name));
    }

    xSemaphoreGive(ctx->mutex);
    return ret;
}

esp_err_t storage_get_info(storage_context_t* ctx, storage_info_t* info)
{
    ESP_RETURN_ON_FALSE(ctx && info, ESP_ERR_INVALID_ARG, TAG, "Invalid args");
    ESP_RETURN_ON_FALSE(ctx->state == STORAGE_STATE_MOUNTED, 
                       ESP_ERR_INVALID_STATE, TAG, "Not mounted");

    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    // 获取存储信息
    size_t total_bytes = 0, used_bytes = 0;
    esp_err_t ret = esp_littlefs_info(ctx->config.partition_label, 
                                    &total_bytes, &used_bytes);
    if (ret == ESP_OK) {
        info->total_bytes = total_bytes;
        info->used_bytes = used_bytes;
        info->free_bytes = total_bytes - used_bytes;
        info->geometry.block_size = CONFIG_LITTLEFS_BLOCK_SIZE;
        info->geometry.block_count = total_bytes / CONFIG_LITTLEFS_BLOCK_SIZE;
        info->limits.total_files = CONFIG_LITTLEFS_MAX_FILES;
        info->limits.open_files = CONFIG_LITTLEFS_MAX_OPEN_FILES;
        info->limits.max_name_len = CONFIG_LITTLEFS_MAX_NAME_LENGTH;
        info->status.is_mounted = true;
        info->status.is_read_only = false;
    }

    xSemaphoreGive(ctx->mutex);
    return ret;
}


// core/storage_ops.c 继续

esp_err_t storage_mkdir(storage_context_t* ctx, const char* path)
{
    ESP_RETURN_ON_FALSE(ctx && path, ESP_ERR_INVALID_ARG, TAG, "Invalid args");
    ESP_RETURN_ON_FALSE(ctx->state == STORAGE_STATE_MOUNTED, 
                       ESP_ERR_INVALID_STATE, TAG, "Not mounted");

    char full_path[CONFIG_LITTLEFS_MAX_NAME_LENGTH];
    if (snprintf(full_path, sizeof(full_path), "%s%s",
                 ctx->config.base_path, path) >= sizeof(full_path)) {
        return ESP_ERR_BUFFER_OVERFLOW;
    }

    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    // 使用LittleFS创建目录
    esp_err_t ret = esp_littlefs_mkdir(ctx->config.partition_label, full_path);
    if (ret == ESP_OK) {
        // 更新存储信息
        size_t total_bytes = 0, used_bytes = 0;
        if (esp_littlefs_info(ctx->config.partition_label, &total_bytes, &used_bytes) == ESP_OK) {
            ctx->info.used_bytes = used_bytes;
            ctx->info.free_bytes = total_bytes - used_bytes;
        }
    }

    xSemaphoreGive(ctx->mutex);
    return ret;
}

esp_err_t storage_rmdir(storage_context_t* ctx, const char* path)
{
    ESP_RETURN_ON_FALSE(ctx && path, ESP_ERR_INVALID_ARG, TAG, "Invalid args");
    ESP_RETURN_ON_FALSE(ctx->state == STORAGE_STATE_MOUNTED, 
                       ESP_ERR_INVALID_STATE, TAG, "Not mounted");

    char full_path[CONFIG_LITTLEFS_MAX_NAME_LENGTH];
    if (snprintf(full_path, sizeof(full_path), "%s%s",
                 ctx->config.base_path, path) >= sizeof(full_path)) {
        return ESP_ERR_BUFFER_OVERFLOW;
    }

    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    // 检查目录是否为空
    esp_littlefs_dir_t *dir;
    esp_err_t ret = esp_littlefs_opendir(ctx->config.partition_label, full_path, &dir);
    if (ret != ESP_OK) {
        xSemaphoreGive(ctx->mutex);
        return ret;
    }

    // 检查目录项
    esp_littlefs_dirent_t *entry;
    bool is_empty = true;
    while (esp_littlefs_readdir(dir, &entry) == ESP_OK && entry != NULL) {
        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
            is_empty = false;
            break;
        }
    }

    esp_littlefs_closedir(dir);

    if (!is_empty) {
        xSemaphoreGive(ctx->mutex);
        return ESP_ERR_NOT_EMPTY;
    }

    // 删除空目录
    ret = esp_littlefs_rmdir(ctx->config.partition_label, full_path);
    if (ret == ESP_OK) {
        // 更新存储信息
        size_t total_bytes = 0, used_bytes = 0;
        if (esp_littlefs_info(ctx->config.partition_label, &total_bytes, &used_bytes) == ESP_OK) {
            ctx->info.used_bytes = used_bytes;
            ctx->info.free_bytes = total_bytes - used_bytes;
        }
    }

    xSemaphoreGive(ctx->mutex);
    return ret;
}

esp_err_t storage_list_dir(storage_context_t* ctx, const char* path,
                          storage_dir_entry_t* entries, size_t* num_entries)
{
    ESP_RETURN_ON_FALSE(ctx && path && entries && num_entries && *num_entries > 0,
                       ESP_ERR_INVALID_ARG, TAG, "Invalid args");
    ESP_RETURN_ON_FALSE(ctx->state == STORAGE_STATE_MOUNTED, 
                       ESP_ERR_INVALID_STATE, TAG, "Not mounted");

    char full_path[CONFIG_LITTLEFS_MAX_NAME_LENGTH];
    if (snprintf(full_path, sizeof(full_path), "%s%s",
                 ctx->config.base_path, path) >= sizeof(full_path)) {
        return ESP_ERR_BUFFER_OVERFLOW;
    }

    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    // 打开目录
    esp_littlefs_dir_t *dir;
    esp_err_t ret = esp_littlefs_opendir(ctx->config.partition_label, full_path, &dir);
    if (ret != ESP_OK) {
        xSemaphoreGive(ctx->mutex);
        return ret;
    }

    // 读取目录内容
    size_t count = 0;
    const size_t max_entries = *num_entries;
    esp_littlefs_dirent_t *entry;

    while (count < max_entries && 
           esp_littlefs_readdir(dir, &entry) == ESP_OK && 
           entry != NULL) {
        // 跳过 . 和 ..
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        // 获取文件详细信息
        char entry_path[CONFIG_LITTLEFS_MAX_NAME_LENGTH];
        snprintf(entry_path, sizeof(entry_path), "%s/%s", full_path, entry->d_name);

        esp_littlefs_file_stat_t stat;
        if (esp_littlefs_stat(ctx->config.partition_label, entry_path, &stat) == ESP_OK) {
            storage_file_info_t* info = &entries[count].info;
            strlcpy(info->name, entry->d_name, sizeof(info->name));
            info->size = stat.size;
            info->type = (stat.type == ESP_LITTLEFS_TYPE_DIR) ? 
                        STORAGE_TYPE_DIRECTORY : STORAGE_TYPE_REGULAR;
            info->create_time = stat.ctime;
            info->modify_time = stat.mtime;
            count++;
        }
    }

    esp_littlefs_closedir(dir);
    *num_entries = count;

    xSemaphoreGive(ctx->mutex);
    return ESP_OK;
}

esp_err_t storage_exists(storage_context_t* ctx, const char* path, bool* exists)
{
    ESP_RETURN_ON_FALSE(ctx && path && exists, 
                       ESP_ERR_INVALID_ARG, TAG, "Invalid args");
    ESP_RETURN_ON_FALSE(ctx->state == STORAGE_STATE_MOUNTED, 
                       ESP_ERR_INVALID_STATE, TAG, "Not mounted");

    char full_path[CONFIG_LITTLEFS_MAX_NAME_LENGTH];
    if (snprintf(full_path, sizeof(full_path), "%s%s",
                 ctx->config.base_path, path) >= sizeof(full_path)) {
        return ESP_ERR_BUFFER_OVERFLOW;
    }

    xSemaphoreTake(ctx->mutex, portMAX_DELAY);

    // 检查文件是否存在
    esp_littlefs_file_stat_t stat;
    esp_err_t ret = esp_littlefs_stat(ctx->config.partition_label, full_path, &stat);
    *exists = (ret == ESP_OK);

    xSemaphoreGive(ctx->mutex);
    return ESP_OK;
}








